package com.ndhutu.ee.util.pay.zfpai;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ndhutu.ee.util.MD5Util;
import com.ndhutu.ee.util.http.OKHttpUtil;
import com.ndhutu.ee.util.pay.Notify;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

/**
 * @Author Shane
 * @Date 2020/8/31 15:27
 */
public class ZFPaiPayUtil {
    private static Logger log = LoggerFactory.getLogger(ZFPaiPayUtil.class);

    /**
     * 获取签名
     * @Author Shane
     * @Date 2020/8/31 15:40
     * @param 
     * @return 
     */
    public static String getSign(Map<String, String> params, ZFPaiPayConfig config){
        Set<String> sets = params.keySet();
        List<String> keys = new ArrayList<>(sets);
        Collections.sort(keys);

        StringBuffer buffer = new StringBuffer();
        for(String key : keys){
            buffer.append("&").append(params.get(key));
        }

        String str = buffer.toString() + "&" + config.getSecret();

        String sign = MD5Util.encode32(str).toUpperCase();

        return sign;
    }

    /**
     * 支付下单
     * @Author Shane
     * @Date 2020/8/31 16:03
     * @param payWay    支付方式，0-微信  1-支付宝
     * @return
     */
    public static Map<String, Object> order(ZFPaiPayConfig config, Integer payWay, Integer userId, String orderNumber, Integer amount, String subject, String body) throws Exception{
        Map<String, String> params = new HashMap<>();

        params.put("P1_bizType", "AppQuickPayHtml");
        params.put("P2_orderId", orderNumber);
        params.put("P3_customerNumber", config.getCustomerNumber());
        params.put("P4_orderAmount", amount/100.0 + "");
        params.put("P5_currency", "CNY");
        if(payWay == 0){
            params.put("P6_appType", "WXPAY");
        }else if(payWay == 1){
            params.put("P6_appType", "ALIPAY");
        }else{
            throw new Exception("未知的支付方式");
        }
        params.put("P7_userId", userId+"");
        params.put("P8_notifyUrl", config.getNotifyUrl());
        params.put("P9_successToUrl", config.getSuccessToUrl());
        params.put("P10_falseToUrl", config.getFalseToUrl());
        params.put("P11_goodsName", subject);
        params.put("P12_goodsDetail", body);

        String str = "&"+params.get("P1_bizType")
                +"&"+params.get("P2_orderId")
                +"&"+params.get("P3_customerNumber")
                +"&"+params.get("P4_orderAmount")
                +"&"+params.get("P5_currency")
                +"&"+params.get("P6_appType")
                +"&"+params.get("P7_userId")
                +"&"+params.get("P8_notifyUrl")
                +"&"+params.get("P9_successToUrl")
                +"&"+params.get("P10_falseToUrl")
                +"&"+params.get("P11_goodsName")
                +"&"+params.get("P12_goodsDetail")
                +"&"+config.getSecret();
        String sign = MD5Util.MD5(str).toUpperCase();
        params.put("sign", sign);

        String json = OKHttpUtil.post(config.getPayUrl(), params);
        log.info("支付派下单返回结果："+json);

        Map<String, Object> result = JSON.parseObject(json, Map.class);
        str = "&"+result.get("rt1_bizType")
                +"&"+result.get("rt2_retCode")
                +"&"+result.get("rt4_customerNumber")
                +"&"+result.get("rt5_orderId")
                +"&"+result.get("rt6_appPayType")
                +"&"+result.get("rt7_orderAmount")
                +"&"+result.get("rt8_currency")
                +"&"+result.get("rt9_userId")
                +"&"+result.get("rt10_appPayUrl")
                +"&"+config.getSecret();
        if(result.get("sign").equals(MD5Util.MD5(str).toUpperCase())){
            return result;
        }else{
            log.error("返回结果签名错误");
            throw new Exception("支付派下单失败");
        }
    }

    /**
     * 支付回调
     * @Author Shane
     * @Date 2020/8/31 18:47
     * @param
     * @return
     */
    public static String notify(HttpServletRequest request, ZFPaiPayConfig config, Notify notify) throws Exception{
        Map<String,String> params = new HashMap<String, String>();

        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        log.debug("支付派支付回调参数："+ JSONObject.toJSONString(params));

        //签名验证
        String str = "&"+params.get("rt1_customerNumber")
                +"&"+params.get("rt2_orderId")
                +"&"+params.get("rt3_systemSerial")
                +"&"+params.get("rt4_status")
                +"&"+params.get("rt5_orderAmount")
                +"&"+params.get("rt6_currency")
                +"&"+params.get("rt7_timestamp")
                +"&"+params.get("rt8_desc")
                +"&"+config.getSecret();
        String sign = MD5Util.MD5(str).toUpperCase();
        if(sign != null && sign.equals(params.get("sign"))){
            if("SUCCESS".equals(params.get("rt4_status"))){
                String orderNumber = params.get("rt2_orderId");
                Integer amount = (int)(Double.parseDouble(params.get("rt5_orderAmount")) * 100);

                //统一回调
                notify.handleNotify(orderNumber, amount);
            }
            return "success";
        }

        return "fail";
    }

    /**
     * 获取回调请求参数
     * @param request
     * @return
     * @throws Exception
     */
    public static Map<String, String> getNotifyRequestParams(HttpServletRequest request) throws Exception{
        Map<String,String> params = new HashMap<String, String>();

        Map requestParams = request.getParameterMap();
        for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                        : valueStr + values[i] + ",";
            }
            params.put(name, valueStr);
        }
        log.debug("支付派支付回调参数："+ JSONObject.toJSONString(params));

        return params;
    }

    /**
     * 校验回调请求
     * @param params    回调请求参数
     * @param config
     * @param notify
     * @return
     * @throws Exception
     */
    public static String verifyNotifyRequest(Map<String, String> params, ZFPaiPayConfig config, Notify notify) throws Exception{
        //签名验证
        String str = "&"+params.get("rt1_customerNumber")
                +"&"+params.get("rt2_orderId")
                +"&"+params.get("rt3_systemSerial")
                +"&"+params.get("rt4_status")
                +"&"+params.get("rt5_orderAmount")
                +"&"+params.get("rt6_currency")
                +"&"+params.get("rt7_timestamp")
                +"&"+params.get("rt8_desc")
                +"&"+config.getSecret();
        String sign = MD5Util.MD5(str).toUpperCase();
        if(sign != null && sign.equals(params.get("sign"))){
            if("SUCCESS".equals(params.get("rt4_status"))){
                String orderNumber = params.get("rt2_orderId");
                Integer amount = (int)(Double.parseDouble(params.get("rt5_orderAmount")) * 100);

                //统一回调
                notify.handleNotify(orderNumber, amount);

                log.info("订单" + orderNumber + "支付派回调成功");
            }
            return "success";
        }

        return "fail";
    }
}
